package org.linlinjava.litemall.wx.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.linlinjava.litemall.core.system.SystemConfig;
import org.linlinjava.litemall.core.util.ResponseUtil;
import org.linlinjava.litemall.db.beans.Constants;
import org.linlinjava.litemall.db.domain.*;
import org.linlinjava.litemall.db.service.*;
import org.linlinjava.litemall.wx.annotation.LogAnno;
import org.linlinjava.litemall.wx.annotation.LoginUser;
import org.linlinjava.litemall.wx.service.HomeCacheManager;
import org.linlinjava.litemall.wx.service.WxLumiereCouponStrategyService;
import org.linlinjava.litemall.wx.vo.packagegoods.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.validation.constraints.NotNull;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * WxHome控制器
 * 首页服务
 *
 * @author yliyun
 * @date 2022/09/14
 */
@RestController
@RequestMapping("/wx/home")
@Validated
public class WxHomeController {

    /**
     * 广告服务
     */
    @Autowired
    private LitemallAdService adService;

    /**
     * 商品服务
     */
    @Autowired
    private LitemallGoodsService goodsService;

    /**
     * 目录服务
     */
    @Autowired
    private LitemallCategoryService categoryService;
    @Autowired
    private LumiereGoodsFormulaCorrelationService lumiereGoodsFormulaCorrelationService;

    @Autowired
    private LumiereFormulaSpecificationsService lumiereFormulaSpecificationsService;
    /**
     * 息服务
     */
    @Autowired
    private LitemallCouponService couponService;

    /**
     * 规范服务
     */
    @Autowired
    private LitemallGoodsSpecificationService specService;

    /**
     * 用户服务
     */
    @Autowired
    private LitemallUserService userService;

    /**
     * 优惠券用户服务
     */
    @Autowired
    private LitemallCouponUserService couponUserService;

    /**
     * 店地区服务
     */
    @Autowired
    private LitemallShopRegionService shopRegionService;

    @Autowired
    private LumierePackageService lumierePackageService;

    @Autowired
    private LitemallRegionService litemallRegionService;

    /**
     * 卢米埃支付会员用户服务
     */
    @Autowired
    private LumierePayMemberUserService lumierePayMemberUserService;

    /**
     * 商品地区服务
     */
    @Autowired
    private LitemallGoodsRegionService goodsRegionService;

    @Autowired
    private WxLumiereCouponStrategyService wxLumiereCouponStrategyService;


    /**
     * 工作队列
     */
    private final static ArrayBlockingQueue<Runnable> WORK_QUEUE = new ArrayBlockingQueue<>(9);

    /**
     * 处理程序
     */
    private final static RejectedExecutionHandler HANDLER = new ThreadPoolExecutor.CallerRunsPolicy();

    /**
     * 缓存
     *
     * @param key 关键
     * @return {@link Object}
     */
    @GetMapping("/cache")
    @LogAnno
    public Object cache(@NotNull String key) {
        if (!key.equals("litemall_cache")) {
            return ResponseUtil.fail();
        }

        // 清除缓存
        HomeCacheManager.clearAll();
        return ResponseUtil.ok("缓存已清除");
    }

    /**
     * 首页数据
     *
     * @param userId 当用户已经登录时，非空。为登录状态为null
     * @param shopId 商店id
     * @return 首页数据
     */
    @GetMapping("/index")
    @LogAnno
    public Object index(@LoginUser Integer userId, Integer shopId) {
        //优先从缓存中读取
        /*if (HomeCacheManager.hasData(HomeCacheManager.INDEX)) {
            Map<String, Object> entity = HomeCacheManager.getCacheData(HomeCacheManager.INDEX);
            List<LitemallCoupon> couponList = getCouupons(userId, shopId);
            entity.put("couponList", couponList);
            return ResponseUtil.ok(entity);
        }*/
        ExecutorService executorService = Executors.newFixedThreadPool(10);

        Callable<List> bannerListCallable = () -> {
            List<LitemallAd> ads =  adService.queryIndex();
            ads = ads.stream().filter(ad -> {
                Integer[] shopIds =  ad.getShopIds();
                if(shopIds == null ||  shopIds.length == 0){
                    return true;
                }else{
                    for (int i = 0; i < shopIds.length; i++) {
                        if(shopId!= null && shopIds[i].equals(shopId)){
                            return true;
                        }else if(shopId == null ){
                            return true;
                        }
                    }
                    return false;
                }
            }).collect(Collectors.toList());
            return ads;
        };

        Callable<List> channelListCallable = () -> categoryService.queryChannel();

        Callable<List> couponStrategyListCallable=()->wxLumiereCouponStrategyService.homeCouponList(userId);

        //Callable<List> couponListCallable;

        /*if (userId == null) {
            couponListCallable = () -> couponService.queryList(0, 10000);
        } else {
            couponListCallable = () -> {
                List<LitemallCoupon> couponslist = getCouupons(userId, shopId);
                //得到当前用户优惠券领取数
                couponslist.stream().forEach(coupons->{
                    Integer integer = couponUserService.countUserAndCoupon(userId, coupons.getId());
                    coupons.setHaveNum(integer);
                });
                return couponslist;
            };
        }*/

        Callable<List> newGoodsListCallable = () -> {
            List<LitemallGoods> goodsList = goodsService.queryByNew(0, SystemConfig.getNewLimit());
            // 过滤门店是否在商品所在的区域
            goodsList = goodsList.stream().filter(goods -> {
                List<LitemallGoodsRegion> goodsRegions = goodsRegionService.queryByGid(goods.getId());
                List<Integer> cityIds = goodsRegions.stream().map(LitemallGoodsRegion::getCityId).collect(Collectors.toList());
                List<LitemallShopRegion> shopRegions = shopRegionService.queryByShopIdAndRegionIds(shopId, cityIds);

                if (shopRegions != null && shopRegions.size() > 0) {
                    return true;
                } else {
                    return false;
                }

            }).collect(Collectors.toList());

            for (LitemallGoods litemallGoods : goodsList) {
                litemallGoods.setRetailPrice(getRetailPrice(litemallGoods.getId()).setScale(2));
            }
            return goodsList;
        };

        Callable<List> hotGoodsListCallable = () -> {
            IPage<LitemallGoods> goodsList = goodsService.queryByHot(0, SystemConfig.getHotLimit());

            // 过滤门店是否在商品所在的区域
            List<LitemallGoods> collect = goodsList.getRecords().stream().filter(goods -> {
                List<LitemallGoodsRegion> goodsRegions = goodsRegionService.queryByGid(goods.getId());
                List<Integer> cityIds = goodsRegions.stream().map(LitemallGoodsRegion::getCityId).collect(Collectors.toList());
                List<LitemallShopRegion> shopRegions = shopRegionService.queryByShopIdAndRegionIds(shopId, cityIds);

                if (shopRegions != null && shopRegions.size() > 0) {
                    return true;
                } else {
                    return false;
                }
            }).collect(Collectors.toList());

            collect.forEach(litemallGoods->litemallGoods.setRetailPrice(getRetailPrice(litemallGoods.getId())));
            return collect;
        };


        Callable<List> packageListCallable = () -> packageList(shopId);

        Callable<List> floorGoodsListCallable = this::getCategoryList;
        FutureTask<List> bannerTask = new FutureTask<>(bannerListCallable);
        FutureTask<List> channelTask = new FutureTask<>(channelListCallable);
        //FutureTask<List> couponListTask = new FutureTask<>(couponListCallable);
        FutureTask<List> couponStrategyListTask = new FutureTask<>(couponStrategyListCallable);
        FutureTask<List> newGoodsListTask = new FutureTask<>(newGoodsListCallable);
        FutureTask<List> hotGoodsListTask = new FutureTask<>(hotGoodsListCallable);
        FutureTask<List> floorGoodsListTask = new FutureTask<>(floorGoodsListCallable);

        FutureTask<List> packageListTask = new FutureTask<>(packageListCallable);

        executorService.submit(bannerTask);
        executorService.submit(channelTask);
        //executorService.submit(couponListTask);
        executorService.submit(couponStrategyListTask);
        executorService.submit(newGoodsListTask);
        executorService.submit(hotGoodsListTask);
        executorService.submit(floorGoodsListTask);
        executorService.submit(packageListTask);

        Map<String, Object> entity = new HashMap<>();
        try {
            entity.put("couponStrategyList", couponStrategyListTask.get());
            entity.put("banner", bannerTask.get());
            entity.put("channel", channelTask.get());
            entity.put("newGoodsList", newGoodsListTask.get());
            entity.put("hotGoodsList", hotGoodsListTask.get());
            entity.put("floorGoodsList", floorGoodsListTask.get());
            entity.put("packageList", packageListTask.get());

            //缓存数据
            HomeCacheManager.loadData(HomeCacheManager.INDEX, entity);
        } catch (Exception e) {
            ResponseUtil.fail();
        } finally {
            executorService.shutdown();
        }
        return ResponseUtil.ok(entity);
    }


    public List<LumierePackage> packageList(Integer shopId) {
        //获取所有指定门店 套餐
        List<LumierePackage> packageAll = lumierePackageService.list();

        //门店匹配的 套餐
        List<LitemallShopRegion> shopRegions = shopRegionService.queryByShopId(shopId);
        List<LitemallRegion> regions = litemallRegionService.findByIds(shopRegions.stream().map(shopRegion -> shopRegion.getRegionId()).collect(Collectors.toList()));
        //门店市区
        LitemallRegion regionCity = CollUtil.findOne(regions, region -> region.getType() == Constants.REGION_TYPE_CITY);

        //门店市区 匹配 所有套餐
        List<LumierePackage> packageList =  packageAll.stream()
                .filter(lumierePackage -> {
                    LitemallGoodsRegion byPackageIdAndCityId = goodsRegionService.findByPackageIdAndCityId(lumierePackage.getId(), regionCity.getId());
                    return lumierePackage.getShopId() == shopId || byPackageIdAndCityId != null;
                })
                .collect(Collectors.toList());
        return packageList;
    }

    /**
     * 把零售价格
     *
     * @param goodsId 商品id
     * @return {@link BigDecimal}
     */
    private BigDecimal getRetailPrice(Integer goodsId) {
        LumiereGoodsFormulaCorrelation goodsFormulaCorrelation = lumiereGoodsFormulaCorrelationService.getGoodsFormulaByGoodsId(goodsId);
        List<LumiereFormulaSpecifications> formulaSpecifications = lumiereFormulaSpecificationsService.selectListByFormulaId(goodsFormulaCorrelation.getFormulaId());
        if (CollUtil.isEmpty(formulaSpecifications)) {return BigDecimal.ZERO;}
        LumiereFormulaSpecifications defaultFormulaSpecifications = CollUtil.findOne(formulaSpecifications, item -> item.getIsDefault());
        return defaultFormulaSpecifications!=null?defaultFormulaSpecifications.getSpecificationsPrice():formulaSpecifications.get(0).getSpecificationsPrice();
    }

    /**
     * 得到类别列表
     *
     * @return {@link List}<{@link Map}>
     */
    private List<Map> getCategoryList() {
        List<Map> categoryList = new ArrayList<>();
        List<LitemallCategory> catL1List = categoryService.queryL1WithoutRecommend(0, SystemConfig.getCatlogListLimit());
        for (LitemallCategory catL1 : catL1List) {
            List<LitemallCategory> catL2List = categoryService.queryByPid(catL1.getId());
            List<Integer> l2List = new ArrayList<>();
            for (LitemallCategory catL2 : catL2List) {
                l2List.add(catL2.getId());
            }

            List<LitemallGoods> categoryGoods;
            if (l2List.size() == 0) {
                categoryGoods = new ArrayList<>();
            } else {
                categoryGoods = goodsService.queryByCategory(l2List, 0, SystemConfig.getCatlogMoreLimit());
            }

            Map<String, Object> catGoods = new HashMap<>();
            catGoods.put("id", catL1.getId());
            catGoods.put("name", catL1.getName());
            catGoods.put("goodsList", categoryGoods);
            categoryList.add(catGoods);
        }
        return categoryList;
    }


    /**
     * 得到couupons
     *
     * @param userId 用户id
     * @param shopId 商店id
     * @return {@link List}<{@link LitemallCoupon}>
     */
    public List<LitemallCoupon> getCouupons(Integer userId, Integer shopId) {
        //过滤已经设置为生日福利全的券
        List<LitemallCoupon> coupons = couponService.queryAllByRanges( userId);

        //过滤已领取完的优惠券
        coupons=coupons.stream().filter(coupon->{
            long receiveNum = couponUserService.count(Wrappers.lambdaQuery(LitemallCouponUser.class)
                    .eq(LitemallCouponUser::getUserId, userId)
                    .eq(LitemallCouponUser::getCouponId, coupon.getId()));
            boolean b = Arrays.asList(Convert.toStrArray(coupon.getRanges())).contains("0")||Arrays.asList(Convert.toStrArray(coupon.getRanges())).contains("1") ;
            if(coupon.getLimit()==0&&b){
                return true;
            }
            return receiveNum<coupon.getLimit()&&b;
        }).collect(Collectors.toList());
        /*LitemallUser user = userService.findById(userId);
        List<LumierePayMemberUser> payMemberUsers = lumierePayMemberUserService.listMemberByUserId(userId);
        coupons = coupons.stream().filter(coupon -> {
            boolean flag = false;
            //等级会员匹配
            if (coupon.getLevelMemberType().length == 0 && coupon.getMoneyMemberType().length == 0) {
                flag = true;
            } else {
                Integer[] memberIds = coupon.getLevelMemberType();

                if (memberIds != null) {
                    if (memberIds.length > 0) {
                        for (int i = 0; i < memberIds.length; i++) {
                            if (memberIds[i] == user.getUserLevel().intValue()) {
                                flag = true;
                                break;
                            }
                        }
                    }
                }

                if(!flag){
                    if (coupon.getMoneyMemberType() != null && coupon.getMoneyMemberType().length > 0) {
                        for (int i = 0; i < payMemberUsers.size(); i++) {
                            for (int j = 0; j < coupon.getMoneyMemberType().length; j++) {
                                if (payMemberUsers.get(i).getPayMemberId() == coupon.getMoneyMemberType()[j].intValue()) {
                                    flag = true;
                                    break;
                                }
                            }
                        }
                    }
                }
            }

            if (flag) {
                if (coupon.getUseLimit() != null) {
                    Integer receiveNum = couponUserService.countUserAndCoupon(userId, coupon.getId());
                    if (receiveNum < coupon.getUseLimit()) {
                        flag = true;
                    } else {
                        flag = false;
                    }
                }
            }

            return flag;
        }).collect(Collectors.toList());*/
        return CollUtil.isEmpty(coupons)?CollUtil.newArrayList():coupons;
    }
}
